﻿using System;
using System.Globalization;
using System.Linq;
using LinqToTwitter.Common;
using LitJson;

namespace LinqToTwitter
{
    public class UserStreamReceivedDataEventArgs : EventArgs
    {
        public UserStreamReceivedDataEventArgs(string json)
        {
            this.Json = json;
        }

        public string Json { get; private set; }
    }

    public class UserStreamReceivedStatusEventArgs : UserStreamReceivedDataEventArgs
    {
        public UserStreamReceivedStatusEventArgs(string json)
            : base(json)
        {
            this.Status = new Status(JsonMapper.ToObject(json));
        }

        public Status Status { get; private set; }
    }

    public class UserStreamReceivedDirectMessageEventArgs : UserStreamReceivedDataEventArgs
    {
        public UserStreamReceivedDirectMessageEventArgs(string json)
            : base(json)
        {
            this.DirectMessage = new DirectMessage(JsonMapper.ToObject(json)["direct_message"]);
        }

        public DirectMessage DirectMessage { get; private set; }
    }

    public class UserStreamReceivedDeletedEventArgs : UserStreamReceivedDataEventArgs
    {
        public UserStreamReceivedDeletedEventArgs(string json)
            : base(json)
        {
            var j = JsonMapper.ToObject(json)["delete"][0];
            this.Id = j.GetValue<ulong>("id");
            this.UserId = j.GetValue<ulong>("user_id");
        }

        public ulong Id { get; private set; }
        public ulong UserId { get; private set; }
    }

    public enum UserStreamEventType
    {
        Unknown,
        Follow,
        UserUpdate,
        Favorite,
        Unfavorite,
        Block,
        Unblock,
        ListCreated,
        ListDestroyed,
        ListUpdated,
        ListMemberAdded,
        ListMemberRemoved,
        ListUserSubscribed,
        ListUserUnsubscribed
    }

    public class UserStreamReceivedEventEventArgs : UserStreamReceivedDataEventArgs
    {
        public UserStreamReceivedEventEventArgs(string json)
            : base(json)
        {
            var parsed = JsonMapper.ToObject(json);

            this.EventStr = parsed.GetValue<string>("event");

            try
            {
                this.Event = (UserStreamEventType)Enum.Parse(
                    typeof(UserStreamEventType),
                    this.EventStr.Replace("_", ""),
                    true);
            }
            catch
            {
                this.Event = UserStreamEventType.Unknown;
            }

            this.CreatedAt = DateTime.ParseExact(parsed.GetValue<string>("created_at"), "ddd MMM dd HH:mm:ss %zzzz yyyy", CultureInfo.InvariantCulture);
            this.Source = new User(parsed["source"]);
            this.Target = new User(parsed["target"]);

            var targetObject = parsed.GetValue<JsonData>("target_object");
            if (targetObject != null)
            {
                if (targetObject.GetValue<JsonData>("mode") != null)
                {
                    this.TargetList = new List(targetObject);
                }
                else if (targetObject.GetValue<JsonData>("text") != null
                    && targetObject.GetValue<JsonData>("sender") == null)
                {
                    this.TargetStatus = new Status(targetObject);
                }
            }
        }

        public UserStreamEventType Event { get; private set; }
        public string EventStr { get; private set; }
        public DateTime CreatedAt { get; private set; }
        public User Source { get; private set; }
        public User Target { get; private set; }
        public Status TargetStatus { get; private set; }
        public List TargetList { get; private set; }
    }

    public class UserStreamReceivedFriendsEventArgs : UserStreamReceivedDataEventArgs
    {
        public UserStreamReceivedFriendsEventArgs(string json)
            : base(json)
        {
            this.Friends = JsonMapper.ToObject(json)["friends"]
                .Cast<JsonData>()
                .Select(j => (ulong)j)
                .ToArray();
        }

        public ulong[] Friends { get; private set; }
    }
}
